package cn.wolfcode.luowowo.service.impl;

import cn.wolfcode.luowowo.domain.Destination;
import cn.wolfcode.luowowo.domain.Region;
import cn.wolfcode.luowowo.query.DestinationQuery;
import cn.wolfcode.luowowo.repository.DestinationRepository;
import cn.wolfcode.luowowo.service.IDestinationService;
import cn.wolfcode.luowowo.service.IRegionService;
import cn.wolfcode.luowowo.util.DBHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
//@Transactional  暂时先别管事务
public class DestinationServiceImpl implements IDestinationService {
    
    @Autowired
    private DestinationRepository repository;
    
    @Autowired
    private MongoTemplate template;
    
    @Autowired
    private IRegionService regionService;
    
    
    public Destination get(String id) {
        Optional<Destination> optional = repository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }
    
    //page对象里面包括: 总页数 每页显示条数......
    public Page<Destination> query(DestinationQuery qo) {
        /*创建一个空的条件*/
        Query query = new Query();
        /*判断前端传来的父类id是否为空*/
        if (StringUtils.hasLength(qo.getParentId())) {
            /*不为空 条件拼接 查询父类id为传进来的id的值*/
            query.addCriteria(Criteria.where("parentId").is(qo.getParentId()));
        } else {
            /*空 条件查询父类id 为null 的区域*/
            query.addCriteria(Criteria.where("parentId").is(null));
        }
        
        /*模糊高查*/
        if (StringUtils.hasLength(qo.getKeyword())) {
            /*通过name模糊查询*/
            query.addCriteria(Criteria.where("name").regex(".*" + qo.getKeyword() + ".*"));
        }
       // PageRequest pageRequest = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.ASC, "_id");
    
        /*工具类传进条件后 进行数据的排序与分页*/
        return DBHelper.query(template, Destination.class, query, qo.getPageable());
        
    }
    
    public List<Destination> list() {
        return repository.findAll();
    }
    
    public List<Destination> getDestByRegionId(String rid) {
        
        //查询挂载的目的地id集合
        Region region = regionService.get(rid);
        List<String> refIds = region.getRefIds();
        //select from dest where id in (refIds)
        return repository.findByIdIn(refIds);
    }
    
    
    public List<Destination> getDestByRegionIdForApi(String regionId) {
        /*建立一个空的数组为存放数据*/
        List<Destination> list = null;
        /*得到前端传的区域id 判断是否为-1  -1就是中国*/
        if ("-1".equals(regionId)) {
            /*根据name去获取符合条件的目的地对象的集合*/
            list = repository.findByParentName("中国");
        } else {
            /*如果不是中国 就根据区域id去获取区域的对象*/
            Region region = regionService.get(regionId);
            /*通过区域对象获取其中的目的地id集合*/
            List<String> refIds = region.getRefIds();
            /*通过目的地id集合来获得目的地对象集合 存进空的list中*/
            list = repository.findByIdIn(refIds);
        }
        
        
        /*拿到的list对象集合进行循环,拿到里面的数据*/
        for (Destination dest : list) {
            /*
              前端显示限制长度
             * 更好的方法是前端显示一个"更多"的按钮
             * 比较麻烦 先不写
             * */
            PageRequest of = PageRequest.of(0, 5);
            /*通过父类的id查询对应的关联目的地 加上条件限制前端界面的目的地显示数量
             * */
            List<Destination> lists = repository.findByParentId(dest.getId(), of);
            /*将获取的子目的地集合存进真实类中的空集合中*/
            dest.setChildren(lists);
        }
        //返回list  里面是获取的目的地与获取的子目的地集合
        return list;
    }
    
    /*获取前端吐司*/
    public List<Destination> getToasts(String parentId) {
        /*如果前端的区域id为空的话*/
        if (!StringUtils.hasLength(parentId)) {
            //返回一个空集合
            return Collections.emptyList();
        }
        List<Destination> list = new ArrayList<>();
        //查询当前目的地
        createToast(list, parentId);
        Collections.reverse(list);  //取反
        return list;
    }
    
    //创建toast 也可以用while的方法 这里使用递归的方式
    private void createToast(List<Destination> list, String parentId) {
        /*通过id获取对象*/
        Destination destination = this.get(parentId);
        /*对象存入list集合中*/
        list.add(destination);
        /*判断id是否为空*/
        if (StringUtils.hasLength(destination.getParentId())) {
            /*不为空说明是有父类的 就再调用递归方法再循环一次
            * 为空就会跳过这个方法 返回结果list*/
            createToast(list, destination.getParentId());
        }
    }
    
    @Override
    public Destination getByName(String keyword) {
        return repository.findByName(keyword);
    }
    
    @Override
    public List<Destination> queryByRegion(String rid) {
        //先通过区域的id获取目的地的id集合
        Region region = regionService.get(rid);
        List<String> ids = region.getRefIds();
        System.out.println(ids);
        //通过mongodb里面的集合获取方法获取到目的地的数据
        System.out.println(repository.findByIdIn(ids));
        return repository.findByIdIn(ids);
    }
    
    @Override
    public void delete(String id) {
        repository.deleteById(id);
    }
    
    /**
     * 保存修改后的简介方法
     * @param destination 对象,其中包含id 与新简介
     */
    @Override
    public void updateInfo(Destination destination) {
        /*mongodb的修改都是全量修改的  所以需要先查找到当前用户的对象信息,修改指定的数据后再给数据库传回整个对象*/
        Destination newDestination1 = repository.findById(destination.getId()).get();
        //修改对象中的简介
        newDestination1.setInfo(destination.getInfo());
        //然后整个对象进行重新添加
        repository.save(newDestination1);
    }
    
    @Override
    public Destination findByDestName(String keyword) {
        Destination byName = repository.findByName(keyword);
        return byName;
    }
}
